package com.heima.user.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.heima.common.exception.CustException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.pojos.UserModel;
import com.heima.user.listen.CommonListen;
import com.heima.user.mapper.ApUserImportMapper;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.ApUserImportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class ApUserImportServiceImpl implements ApUserImportService {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ApUserMapper apUserMapper;
    @Autowired
    ApUserImportMapper apUserImportMapper;

    //重复的集合
    private static List<UserModel> list2 = new ArrayList<>();
    //产生的唯一数用于下载重复的集合时的判断
    private static String repetitionIdUUID = UUID.randomUUID().toString().replace("-","");

    /**
     * 将xlsx的数据批量导入数据库
     * @param file
     * @return
     */
    @Override
    public ResponseResult importUser(MultipartFile file) {
        //1.参数检查
        if (file==null) {
            log.error("上传文件不存在~~~");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2 获取数据
        //2.1用来装存入前端传来的数据集合
        List<UserModel> list = new ArrayList<>();
        //2.1用来装存入数据库的数据集合不重复的集合
        List<ApUser> list3 = new ArrayList<>();
        //重复的
        list2 = new ArrayList<>();
        //2.2查询数据库的用户
        List<ApUser> users = apUserMapper.selectList(null);
        try {
            //2.3 用EasyExcel封装前端传来的数据，存入UserModel中
            CommonListen<UserModel> commonListen = new CommonListen<UserModel>(UserModel.class);
            EasyExcel.read(file.getInputStream(), UserModel.class, commonListen).sheet().doRead();
            // 2.4获取导入的数据集合
            list = commonListen.getList();
            // 打印所有导入的数据
            //list.forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("Excel表格信息导入失败：EasyExcel导入数据失败");
        }

        //3.将得到的数据存入redis中
        //3.1将查询用户存入Redis中，用于后来判定手机号是否重复
        for (ApUser user : users) {
            String phone = user.getPhone();
            redisTemplate.boundSetOps("phone").add(phone);
        }
        //导入成功后，给用户提示成功导入多少条：没有重复的导入
        int successNumber = 0;
        //导入成功后，给用户提示多少条没有导入(原因是手机号重复)
        int repetitionNumber = 0;
        //3.3遍历前端传来的数据
        for (UserModel userModel : list) {
            //3.4判断手机号是否有重复的，重复得到true
            String phone = userModel.getPhone();
            Boolean judge = redisTemplate.opsForSet().isMember("phone", phone);
            if (StringUtils.isBlank(userModel.getPhone())){
                userModel.setPhone("null");
            }
            if (judge||userModel.getPhone().equals("null")){
                //3.5将重复和为空前端用户手机号存入Redis：另起一个key中
                redisTemplate.boundSetOps("phone2").add(phone);
                //存入全局参数list2中，用于后面的下载
                list2.add(userModel);
                repetitionNumber++;
            }else {
                //3.6将不重复前端用户手机号存入Redis：后端手机号key中
                redisTemplate.boundSetOps("phone").add(phone);
                //3.7将不重复前端用户存入list3,用于存入数据库
                ApUser apUser = new ApUser();
                BeanUtils.copyProperties(userModel,apUser);
                if (userModel.getSex().equals("男")){
                    apUser.setSex(false);
                }else if (userModel.getSex().equals("女")){
                    apUser.setSex(true);
                }
                apUser.setCreatedTime(new Date());
                apUser.setFlag((short)0);
                apUser.setStatus(false);
                //System.out.println(apUser);
                if (apUser == null){
                    break;
                }
                list3.add(apUser);
                //3.8list中每有一条就加一
                successNumber++;
            }
            //3.9当list3数据中有2500条时就存入数据库
            if (successNumber==2000){
                apUserImportMapper.saveUser(list3);
                //归零，重新计算
                list3 = new ArrayList<>();
                successNumber=0;
            }
        }
        //3.10将list3数据中还有的用户存入数据库
        if (successNumber>0){
            apUserImportMapper.saveUser(list3);
        }
        redisTemplate.boundValueOps("phone2").expire(1, TimeUnit.MINUTES);
        //得到成功导入的数据
        successNumber = list.size()-repetitionNumber;
        //封装数据
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("repetitionNumber", repetitionNumber);
        resultMap.put("successNumber", successNumber);
        resultMap.put("repetitionId",repetitionIdUUID);
        //返回结果
        return ResponseResult.okResult(resultMap);
    }


    /**
     * 将xlsx的数据中重复数据批量导出
     * @param response
     * @param repetitionId
     * @return
     */
    @Override
    public void dowmUsers(HttpServletResponse response, String repetitionId) {
        if (StringUtils.isBlank(repetitionId) || !repetitionId.equals(repetitionIdUUID) ){
            log.error("请传入有效UUID参数~~~");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        response.setContentType("application/binary;charset=UTF-8");
        try{
            ServletOutputStream out=response.getOutputStream();
            try {
                //设置文件头：最后一个参数是设置下载文件名(这里我们叫：张三.pdf)
                response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(repetitionId+".xlsx", "UTF-8"));
            } catch (UnsupportedEncodingException e1) {
                e1.printStackTrace();
            }

            //list2.forEach(System.out::println);
            // 这里 需要指定写用哪个class去写，然后写到第一个sheet，名字为模板 然后文件流会自动关闭
            EasyExcel.write(out, UserModel.class).sheet("重复手机号").doWrite(list2);
            log.info("下载重复手机号成功~~~");
            list2 = new ArrayList<>();

        } catch(Exception e){
            e.printStackTrace();
            log.error("下载重复手机号失败");

        }
    }

}
